import unittest
from functionBinding import functionBinding
from functionDef import functionDef
from application import application
from Return import Return
from builtin import *
from varRef import varRef
from jsobject import *
from interpreter import interpreter
from endvals import *
from objectOps import *
from sequence import *
from conditionals import *
from sequence import *
from varBinding import *
from varMut import *
from customExceptions import *

class TestObjects(unittest.TestCase):
	def testObjectFieldLookupAndMutation(self):
		p = varBinding("obj", jsobject(),
										sequence([
																fieldMutation(varRef("obj"), stringval("test"), integer(1)),
																Return(fieldLookup(varRef("obj"), stringval("test")) )
															 ])
									  )
		i = interpreter(p)	
		assert i.execute() == 1, "testObjectFieldLookupAndMutation Failed! Should have returned 1!"

#--	------------------------------------------------------------------
		
	def testObjectFieldLookupFail(self):
		# Testing if FieldLookup fails on non-object first arg
		p = varBinding("obj", jsobject(),
											Return(fieldLookup(integer(1), stringval("test")) )
									  )
		i = interpreter(p)	
		try:
			i.execute()
		except IncorrectArgumentExcpt:
			assert True	
		else:
			assert False, "Object Field Lookup Fail should have failed on a non-object first arg!"
		# Testing if FeildLookup fails on non-existance field name	
		p = varBinding("obj", jsobject(),
											Return(fieldLookup(varRef("obj"), stringval("test")) )
									  )
		i = interpreter(p)	
		try:
			i.execute()
		except VarNotFoundExcpt:
			assert True	
		else:
			assert False, "Object Field Lookup Fail should have failed to find the field \"test\"!"

#--	------------------------------------------------------------------
		
	def testObjectFieldMutationFail(self):
		# Testing if FieldMutation fails on non-object first arg
		p = varBinding("obj", jsobject(),
											Return(fieldMutation(integer(1), stringval("test"), integer(1) ) )
									  )
		i = interpreter(p)	
		try:
			i.execute()
		except IncorrectArgumentExcpt:
			assert True	
		else:
			assert False, "Object Field Lookup Fail should have failed on a non-object first arg!"
		
	def testMethodCall(self):
		p = functionBinding([ functionDef("test", [], 
																			Return(integer(1))
																			)
												  ],
														varBinding("obj", jsobject(),
																sequence([
																	fieldMutation(varRef("obj"), stringval("test"), varRef("test") ),
																	Return(methodCall(varRef("obj"), stringval("test"), []))
																])
														  )
										 )
		i = interpreter(p)	
		assert i.execute() == 1, "testMethodCall Failed! Expected to return 1!"
		
#--	------------------------------------------------------------------	
		
	def testMethodCallFailure(self):
		# Testing if methodCall fails on non-object first arg
		p = functionBinding([ functionDef("test", [], 
																			Return(integer(1))
																			)
												  ],
														varBinding("obj", jsobject(),
																sequence([
																	fieldMutation(void(), stringval("test"), varRef("test") ),
																	Return(methodCall(varRef("obj"), stringval("test"), []))
																])
														  )
										 )
		i = interpreter(p)	
		try:
			i.execute()
		except IncorrectArgumentExcpt:
			assert True	
		else:
			assert False, "testMethodCallFailure: Method Invocation should have failed on a non-object first arg!"
	
		# Testing if methodCall fails on non-existance method
		p = functionBinding([ functionDef("test", [], 
																			Return(integer(1))
																			)
												  ],
														varBinding("obj", jsobject(),
																sequence([
																	fieldMutation(varRef("obj"), stringval("test"), varRef("test") ),
																	Return(methodCall(varRef("obj"), stringval("blargh"), []))
																])
														  )
										 )
		i = interpreter(p)	
		try:
			i.execute()
		except VarNotFoundExcpt:
			assert True	
		else:
			assert False, "testMethodCallFailure: Method Invocation should have failed when a non-existant member method called!"
			
		# Testing if methodCall fails checks for the correct number of args
		p = functionBinding([ functionDef("test", [], 
																			Return(integer(1))
																			)
												  ],
														varBinding("obj", jsobject(),
																sequence([
																	fieldMutation(varRef("obj"), stringval("test"), varRef("test") ),
																	Return(methodCall(varRef("obj"), stringval("test"), ["bar"]))
																])
														  )
										 )
		i = interpreter(p)	
		try:
			i.execute()
		except GeneralException:
			assert True	
		else:
			assert False, "testMethodCallFailure: Method Invocation should have failed with the wrong number of args!"
		
if __name__ == '__main__':
    unittest.main()